﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Data;
using System.Collections;
using KylinORM.Data.Parser;
using KylinORM.Utils;
using KylinORM.Data;
using KylinORM.Aspect.Definition;
using KylinORM.Data.Parser.Base;

namespace KylinORM.Mapper.Base
{
    /// <summary>
    /// 为IMapper的实现类提供公用方法
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public abstract class MapperBase<T> : ISqlParserData, IMapper, ISubmitable,ICloneable<MapperBase<T>> where T :  new()
    {
        #region 初始化
        /// <summary>
        /// Sql语法解析器的参数
        /// </summary>
        internal SqlParserBase mapperCommand;
        private T entity;
        /// <summary>
        /// 目标实体
        /// </summary>
        public T Entity
        {
            get
            {
                //如果在初始化时尚未传入实体的实例，则在此处实例化
                if ((object)this.entity == (object)default(T))
                    this.entity = new T();
                return this.entity;
            }
            protected set
            {
                this.entity = value;
            }
        }
        /// <summary>
        /// 目标实体属性
        /// </summary>
        internal EntityDefinition EntityDefinition { get; set; }

        internal MapperBase()
            : this(default(T), null)
        {
        }
        internal MapperBase(T targetEntity, IEntityDefinitionRule definitionRule)
        {
            this.Entity = targetEntity;
            this.EntityDefinition = EntityDefinitionMap.GetEntityDefinition<T>(definitionRule);

            mapperCommand = SqlParserProvider.GetInstance(this);
        }

        #endregion

        #region ISqlParserData 成员

        object ISqlParserData.Entity
        {
            get { return this.Entity; }
        }

        EntityDefinition ISqlParserData.EntityDefinition
        {
            get { return this.EntityDefinition; }
        }
        #endregion

        #region IMapper 成员

        /// <summary>
        /// 目标实体的名称
        /// </summary>
        public EntityInfo EntityInfo
        {
            get
            {
                return this.EntityDefinition.EntityInfo;
            }
        }
        /// <summary>
        /// 目标实体的属性列表
        /// </summary>
        public ReadonlyOrderedDictionary<EntityFieldInfo> EntityFieldInfos
        {
            get
            {
                return this.EntityDefinition.EntityFieldInfos;
            }
        }
        /// <summary>
        /// 获取或设置目标实体的值
        /// </summary>
        /// <param name="fieldName"></param>
        /// <returns></returns>
        public object this[string fieldName]
        {
            get
            {
                return EntityFieldInfos[fieldName].GetValue(this.Entity);
            }
            set
            {
                EntityFieldInfos[fieldName].SetValue(this.Entity, value);
            }
        }

        #endregion

        #region ISubmitable 成员

        /// <summary>
        /// 插入实体
        /// </summary>
        /// <returns>刚刚插入的ID，如果主键不是自增长则返回-1</returns>
        public virtual int Create()
        {
            DataQuery query = this.mapperCommand.GetInsertCommand();
            if (this.cmd != null)
                query.Command = this.cmd;
            return this.UpdateIdentity(DataProvider.GetInstance().ExecuteScalar(query));
        }
        /// <summary>
        /// 插入指定实体
        /// </summary>
        /// <param name="entity">需要插入的实体</param>
        /// <returns>刚刚插入的ID，如果主键不是自增长则返回-1</returns>
        public virtual int Create(object entity)
        {
            this.entity = (T)entity;
            return this.Create();
        }
        /// <summary>
        /// 更新主键值
        /// </summary>
        protected int UpdateIdentity(object newID)
        {
            var kv = this.EntityFieldInfos.Where(d => d.Value.IsIdentityField == true);
            if (newID != null && newID != DBNull.Value && kv.Count() > 0)
            {
                this[kv.First().Key] = int.Parse(newID.ToString());
                return int.Parse(newID.ToString());
            }
            return -1;
        }

        /// <summary>
        /// 更新实体，使用主键值作为条件，其他字段值作为参数
        /// </summary>
        /// <returns></returns>
        public virtual bool Update()
        {
            DataQuery query = this.mapperCommand.GetUpdateCommand();
            if (this.cmd != null)
                query.Command = this.cmd;
            return DataProvider.GetInstance().ExecuteNonQuery(query) > 0;
        }
        /// <summary>
        /// 更新指定实体，使用主键值作为条件，其他字段值作为参数
        /// </summary>
        /// <param name="entity">需要更新的实体</param>
        /// <returns></returns>
        public virtual bool Update(object entity)
        {
            this.entity = (T)entity;
            return this.Update();
        }

        /// <summary>
        /// 删除实体，使用已赋值的字段作为条件
        /// </summary>
        /// <returns></returns>
        public virtual bool Delete()
        {
            DataQuery query = this.mapperCommand.GetDeleteCommand();
            if (this.cmd != null)
                query.Command = this.cmd;
            return DataProvider.GetInstance().ExecuteNonQuery(query) > 0;
        }
        /// <summary>
        /// 删除指定实体，使用已赋值的字段作为条件
        /// </summary>
        /// <param name="entity">需要删除的实体</param>
        /// <returns></returns>
        public virtual bool Delete(object entity)
        {
            this.entity = (T)entity;
            return this.Delete();
        }

        private IDbCommand cmd;
        /// <summary>
        /// 使用指定的连接或事务执行后续方法
        /// </summary>
        /// <param name="cmd">包含数据库连接或事务的命令</param>
        /// <returns></returns>
        public virtual ISubmitable Use(IDbCommand cmd)
        {
            MapperBase<T> mapper = this.Clone();
            mapper.cmd = cmd;
            return mapper as ISubmitable;
        }
        #endregion

        #region ICloneable<MapperBase<T>> 成员
        /// <summary>
        /// 创建当前数据映射器实例的副本
        /// </summary>
        /// <returns></returns>
        public MapperBase<T> Clone()
        {
            MapperBase<T> newObj = this.MemberwiseClone() as MapperBase<T>;
            newObj.mapperCommand = SqlParserProvider.GetInstance(newObj);
            return newObj;
        }

        object ICloneable.Clone()
        {
            return this.Clone();
        }
        #endregion
    }

    /// <summary>
    /// 简单实体映射器工厂
    /// </summary>
    public abstract class MapperBase
    {
        /// <summary>
        /// 定义全局实体类型的映射
        /// </summary>
        /// <param name="definitionRule">实体映射规则</param>
        public static void Define(IEntityDefinitionRule definitionRule)
        {
            EntityDefinitionMap.EntityDefinitionRule = definitionRule;
        }
        /// <summary>
        /// 定义指定实体类型的映射
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="definitionRule">实体映射规则</param>
        public static void Define<T>(IEntityDefinitionRule definitionRule)
        {
            EntityDefinitionMap.GetEntityDefinition<T>(definitionRule);
        }
    }
}
